﻿using System;
using System.Drawing;

namespace PlusPlusPaint.Layers.VisualObjects
{
    /// <summary>
    /// Represents a rectangle on the screen which is entirely of one colour
    /// visible.  The dimensions of the rectangle will be equal to the
    /// dimensions of the containing layer.
    /// </summary>
    class FilledEllipse : DynamicallyGeneratedVisualObject
    {
        #region constructors
        public FilledEllipse()
        {

        }

        public FilledEllipse(Point begin, Point end)
        {
            SetBoxAround(begin, end);
        }
        #endregion
        
        #region overrides
        protected override string ObjectTypeName
        {
            get
            {
                return "FilledEllipse";
            }
        }

        public override bool PositionIsInHitbox(Point p)
        {
            return IsInEllipseBoundedBy(this.ClientRectangle, p);
        }

        public override IVisualObject Clone()
        {
            FilledEllipse copy = new FilledEllipse(Location, Location + Size);
            copy.Colour = this.Colour;
            return copy;
        }

        public override void BurnOn(Image im)
        {
            using (Brush br = new SolidBrush(this.Colour))
                Graphics.FromImage(im).FillEllipse(br, this.ClientRectangle);
        }
        #endregion

        #region static methods
        public static bool IsInEllipseBoundedBy(Rectangle r, Point p)
        {
            // An ellipse of dimensions a*b is defined as all points such that
            // the sum of the distances between the point and the two foci is
            // less than or equal to a*2.
            //
            // The UlDistance between the centre of the ellipse (a/2 * b/2) is
            // equal to the square root of a^2 - b^2.  Therefore, we are
            // interested in the distances between the point passed and
            // (a/2 + sqrt(a^2 - b^2), b/2) and (a/2 + sqrt(a^2 - b^2), b/2).
            int lxMiddle;
            int lyMiddle;
            int lxClick;
            int lyClick;
            if (r.Width >= r.Height) // If the height is greater than the width, let's transpose the thing.
            {
                lxMiddle = r.Width / 2;
                lyMiddle = r.Height / 2; // possible rounding errors, but insignificant.
                lxClick = p.X - r.Location.X;
                lyClick = p.Y - r.Location.Y;
            }
            else
            {
                lxMiddle = r.Height / 2;
                lyMiddle = r.Width / 2;
                lxClick = p.Y - r.Location.Y;
                lyClick = p.X - r.Location.X;
            }
            int UlxDistanceFromCentreToFoci = (int)Math.Sqrt(lxMiddle * lxMiddle - lyMiddle * lyMiddle);
            int lxLeftFoci = lxMiddle - UlxDistanceFromCentreToFoci;
            int lxRightFoci = lxMiddle + UlxDistanceFromCentreToFoci;
            int UlyDistanceToLociSquared = (lyClick - lyMiddle) * (lyClick - lyMiddle);
            int UlDistanceToLeftLociSquared = (lxClick - lxLeftFoci) * (lxClick - lxLeftFoci) + UlyDistanceToLociSquared;
            int UlDistanceToRightLociSquared = (lxClick - lxRightFoci) * (lxClick - lxRightFoci) + UlyDistanceToLociSquared;
            int UlTotalDistanceToLoci = (int)(Math.Sqrt(UlDistanceToLeftLociSquared) + Math.Sqrt(UlDistanceToRightLociSquared));
            return UlTotalDistanceToLoci < 2 * lxMiddle;
        }
        #endregion
    }
}
